package httplib

import (
	"bytes"
	"compress/gzip"
	"io"
	"os"
)

// GzFileReader 通过 gzip 压缩发送文件
// Example:
//
//	body, bErr := gzFileReader(sendFilepath)
//	if bErr != nil {
//		return bErr
//	}
//
//	req, _ := http.NewRequest("POST", uri, body)
//	//req.Header.Set("Content-Type", contentType)
//	// 自动使用 gzip 对数据进行压缩
//	req.Header.Add("Content-Encoding", "gzip")
//	req.Header.Add("Accept-Encoding", "gzip")
//	resp, hErr := http.DefaultClient.Do(req)
//
// Server:
//
//	filename := ctx.GetHeader("upload-filename")
//
//	rawData, rErr := ctx.GetRawData()
//	if rErr != nil {
//		response.Error(controller.ErrorDataValid, rErr.Error())
//		return
//	}
//	if ctx.GetHeader("Content-Encoding") == "gzip" {
//		rawData, rErr = gunzip(rawData)
//		if rErr != nil {
//			response.Error(controller.ErrorDataValid, rErr.Error())
//			return
//		}
//	}
func GzFileReader(fname string) (io.ReadCloser, error) {
	f, err := os.Open(fname)
	if err != nil {
		return nil, err
	}

	// Use io.Pipe and a goroutine to create reader
	// on data written by the appliation.
	r, w := io.Pipe()
	go func() {
		// Always close the file.
		defer f.Close()

		// Copy file through gzip to pipe writer.
		gzw := gzip.NewWriter(w)
		_, err := io.Copy(gzw, f)

		// Use CloseWithError to propgate errors back to
		// the main goroutine.
		if err != nil {
			w.CloseWithError(err)
			return
		}

		// Flush the gzip writer.
		w.CloseWithError(gzw.Close())
	}()
	return r, nil
}

// Gunzip 解压 gzip 上传的数据
func Gunzip(b []byte) ([]byte, error) {
	reader, err := gzip.NewReader(bytes.NewReader(b))
	if err != nil {
		return nil, err
	}
	defer reader.Close()

	return io.ReadAll(reader)
}
